#ifndef EYAS_CORE_THREAD_AUTOTHREAD_H_
#define EYAS_CORE_THREAD_AUTOTHREAD_H_

#include <boost/noncopyable.hpp>
#include <boost/thread/thread.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>

#include "conf/def.h"

namespace eyas {
namespace thread {

class EYAS_THREAD_API auto_thread : public boost::noncopyable {
public:
	template<typename F, typename... Args>
	auto_thread(F f, Args... args);
	virtual ~auto_thread() = default;

private:
	template<typename F, typename... Args>
	class auto_thread_impl : public boost::noncopyable, public boost::enable_shared_from_this<auto_thread_impl<F, Args...>>{
	public:
		auto_thread_impl()
		:thread_(nullptr){
		}
		~auto_thread_impl(){
			if(nullptr != this->thread_ && this->thread_->get_id() != boost::this_thread::get_id()){
				// 外部介入释放，则需要等待
				this->thread_->join();
			}else{
				// 自己释放自己
			}
			if(nullptr != this->thread_){
				delete this->thread_;
				this->thread_ = nullptr;
			}
		}
	private:
		boost::mutex mutex_;
		boost::thread* thread_;

		void thread_proc(F f, Args... args){
			{	// 用于防止thread_未被赋值时，此语句被执行
				boost::mutex::scoped_lock lck(mutex_);
			}
			f();
			if(nullptr != this->thread_){
				delete this->thread_;
				this->thread_ = nullptr;
			}
		}
	public:
		void start_thread(F threadProc, Args... args){
			boost::mutex::scoped_lock lck(mutex_);
			if(nullptr != thread_){
				return;
			}
			thread_ = new boost::thread(boost::bind(&auto_thread_impl<F>::thread_proc, this->shared_from_this(), threadProc, args...));
		}
	};
};

template<typename F, typename... Args>
auto_thread::auto_thread(F f, Args... args){
	boost::shared_ptr<auto_thread_impl<F>> th_ptr(new auto_thread_impl<F>());
	th_ptr->start_thread(f);
}
}
}

#endif
